﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//非类型模板参数：

//模板参数分类类型形参与非类型形参。
//1.类型形参即：出现在模板参数列表中，跟在class或者typename之类的参数类型名称。
//2.非类型形参，就是用一个常量作为类(函数)模板的一个参数，在类(函数)模板中可将该参数当成常
//量来使用。
namespace Lin
{
	// 定义一个模板类型的静态数组
	template<class T, size_t N = 10>
	class array
	{
	public:
		T& operator[](size_t index) { return _array[index]; }
		const T& operator[](size_t index)const { return _array[index]; }
		size_t size()const { return _size; }
		bool empty()const { return 0 == _size; }
	private:
		T _array[N]; //固定大小的数组
		size_t _size;
	};
}
//注意：
//1. int、浮点数、类对象以及字符串是不允许作为非类型模板参数的。
//2. 非类型的模板参数必须在编译期就能确认结果。



//模板的特化：

//通常情况下，使用模板可以实现一些与类型无关的代码，但对于一些特殊类型的可能会得到一些
//错误的结果，需要特殊处理，比如：实现了一个专门用来进行小于比较的函数模板


//函数模板的特化步骤：
//1. 必须要先有一个基础的函数模板
//2. 关键字template后面接一对空的尖括号 < >
//3. 函数名后跟一对尖括号，尖括号中指定需要特化的类型
//4. 函数形参表: 必须要和模板函数的基础参数类型完全相同，如果不同编译器可能会报一些奇
//怪的错误。


template<class T>
bool Less(T& left, T& right)
{
	return left < right;
}

template<>
bool Less<int*> (int* &left, int* &right) 
{
	return *left < *right;
}


//注意：一般情况下如果函数模板遇到不能处理或者处理有误的类型，为了实现简单通常都是将该
//函数直接给出：
bool Less1(int* left, int* right)
{
	return *left < *right;
}
//该种实现简单明了，代码的可读性高，容易书写，因为对于一些参数类型复杂的函数模板，特化
//时特别给出，因此函数模板不建议特化。

void test()
{
	int a = 1;
	int& p = a;
	int& const pp = a;
	const int& ppp = a;
}
int main()
{
	const int c = 10;
	const int* cp = &c;
	int a = 1;
	int b = 1;
	int* p = &a;
	int* p1 = &b;

	int* x1 = &a;
	*x1;
	*x1 = 10;

	const int*& x = cp; //x是引用，它引用了一个指向const int的指针，可以访问内容，但不能修改内容
	*x;
	//*x = 10;

	int* const& x2 = p;//x是引用，它引用了一个const的指向int的指针。
	*x2;               //这里的const是放在*和&之间的，所以它修饰的是指针本身，而不是指针指向的内容。
	*x2 = 10;          //可以修改指针所指向的值
	//x2 = p1;           //但不能改变指针的指向

	test();
	return 0;
}